
/**
 * 深拷贝和浅拷贝的区别
 * js分为基本类型和引用类型，对于基本类型的拷贝，并没有深浅拷贝的区别，我们讨论的深浅拷贝都只针对引用类型
 * 浅拷贝和深拷贝都复制了值和地址，都是为了解决引用类型赋值后相互影响的问题
 * 但是浅拷贝只进行了一层复制，深层次的引用类型还是共享内存地址，原对象和拷贝对象还是会互相影响；
 * 深拷贝就是无限层级拷贝，深拷贝后的原对象不会和拷贝对象相互影响
 */

//实现浅拷贝
//如： Object.assign 、 数组的 slice 和 concat 方法、 数组静态方法 Array.from 、 扩展运算符


//实现深拷贝
function deepClone(obj){
    // 处理null或者undefined
    if(obj == null) return obj
    // 处理日期类型
    if(obj instanceof Date) return new Date(obj)
    // 处理正则类型
    if(obj instanceof RegExp) return new RegExp(obj)
    // 普通值或函数不需要深拷贝
    if(typeof obj !== 'object') return obj
    let newObj = obj instanceof Array ? [] : {}
    for(let key in obj){
        if(obj.hasOwnProperty(key)){
            newObj[key] = typeof obj[key] === 'object' ? this.deepClone(obj[key]) : obj[key]
        }
    }
    return newObj
}


//数据类型的判断
//Object.prototype.toString.call() 是最准确最常用的方式
Object.prototype.toString.call('') ;   // [object String]
Object.prototype.toString.call(1) ;    // [object Number]
Object.prototype.toString.call(true) ; // [object Boolean]
Object.prototype.toString.call(undefined) ; // [object Undefined]
Object.prototype.toString.call(null) ; // [object Null]
Object.prototype.toString.call(new Function()) ; // [object Function]
Object.prototype.toString.call(new Date()) ; // [object Date]
Object.prototype.toString.call([]) ; // [object Array]
Object.prototype.toString.call(new RegExp()) ; // [object RegExp]
Object.prototype.toString.call(new Error()) ; // [object Error]

//判断数组方式有哪些
let a = []
console.log(Array.isArray(a)) // true
console.log(Object.prototype.toString.call(a)) //‘[object Array]’
console.log(a.constructor === Array) // true
console.log(Array.prototype.isPrototypeOf(a)) // true
console.log( a instanceof Array) // true

let obj = {}
console.log(JSON.stringify(obj))

//实现深拷贝、手写递归
function checkType(target){
    return Object.prototype.toString.call(target).slice(8,-1)
}

// 实现深度克隆 对象/数组
function clone(target){
    let result,
    targetType = checkType(target)
    if(targetType === 'Object'){
        result = {}
    } else if(targetType === 'Array'){
        result = []
    } else {
        return target
    }
    for(let key in target){
        if(target.hasOwnProperty(key)){
            let value = target[key]
            let type = checkType(value)
            if(type === 'Object' || type === 'Array'){
                result[key] = clone(value)
            } else {
                result[key] = value
            }
        }
    }
    return result
}

//深拷贝
const obj = {}
const cloneObj = JSON.parse(JSON.stringify(obj))


// 注意
console.log(null == null, null === null, undefined == undefined, undefined === undefined, null == undefined, undefined === null) // true true true true true false